package com.huahua.api.service.impl;

import com.huahua.api.entity.param.DesParam;
import com.huahua.api.exception.CommonException;
import com.huahua.api.service.DesService;
import com.huahua.api.util.CheckUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.crypto.Mode;
import org.dromara.hutool.crypto.Padding;
import org.dromara.hutool.crypto.symmetric.DES;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * DES加解密服务实现
 */
@Slf4j
@Service
public class DesServiceImpl implements DesService {

    @Override
    public Mono<String> process(DesParam param) {
        return Mono.fromCallable(() -> {
            try {
                CheckUtil.checkStrNotBlank(param.getContent(), new CommonException("内容不能为空"));
                CheckUtil.checkStrNotBlank(param.getKey(), new CommonException("密钥不能为空"));
                CheckUtil.checkStrNotBlank(param.getOperation(), new CommonException("操作类型不能为空"));

                // 密钥长度校验
                byte[] keyBytes = param.getKey().getBytes(StandardCharsets.UTF_8);
                if (keyBytes.length != 8) {
                    throw new CommonException("DES密钥长度必须是8字节");
                }

                DES des;
                try {
                    Mode mode = Mode.valueOf(param.getMode());
                    Padding padding = Padding.valueOf(param.getPadding());

                    if (mode == Mode.CBC) {
                        CheckUtil.checkStrNotBlank(param.getIv(), new CommonException("CBC模式需要提供偏移量(IV)"));
                        byte[] ivBytes = param.getIv().getBytes(StandardCharsets.UTF_8);
                        if (ivBytes.length != 8) {
                            throw new CommonException("IV长度必须是8字节");
                        }
                        des = new DES(mode, padding, keyBytes, ivBytes);
                    } else {
                        des = new DES(mode, padding, keyBytes);
                    }
                } catch (IllegalArgumentException e) {
                    throw new CommonException("不支持的加密模式或填充方式");
                }

                String result;
                switch (param.getOperation()) {
                    case "encrypt":
                        // 加密并Base64编码
                        result = des.encryptBase64(param.getContent());
                        break;
                    case "decrypt":
                        // Base64解码并解密
                        result = des.decryptStr(param.getContent());
                        break;
                    default:
                        throw new CommonException("不支持的操作类型，请使用encrypt或decrypt");
                }

                log.debug("DES操作完成，类型：{}，模式：{}", param.getOperation(), param.getMode());
                return result;
            } catch (CommonException e) {
                // 参数校验异常直接抛出
                throw e;
            } catch (Exception e) {
                // 记录详细错误日志，但不暴露给用户
                log.error("DES操作失败，操作类型：{}", param.getOperation(), e);
                String errorMessage = "encrypt".equals(param.getOperation()) ? "加密失败" : "解密失败";
                throw new CommonException(errorMessage);
            }
        });
    }
}
